all files / src/validators/ battle.validator.ts

100% Statements 27/27
100% Branches 12/12
100% Functions 4/4
100% Lines 24/24
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53        23×     22×     14×   13× 13× 13× 13×       12× 12×                 13×     17×     16×          
import { Action, ThrowCard } from '../game.actions';
import { Game, Battle, Suit, Card, Phase, PlayersCards, CardPattern } from '../game.interfaces';
import { getNextTrickTurn, isTrumpAnnounced, getTrumpSuit, isTableEmpty, getLeadCard, getPlayerByTrickCard, getCardSuit } from '../helpers/battle.helpers';
import * as _ from 'lodash';
import { getCardsByColor, getCardWithHighestRank, cardExistsIn } from '../helpers/cards.helpers';
 
export function canThrowCard(state: Game, { player, card }: ThrowCard) {
    
    // should be in specific phase
    if (state.phase !== Phase.TRICK_IN_PROGRESS) { return false; }
    
    // should be in player turn
    if (getNextTrickTurn(state) !== player) { return false; }
    
    // should have the card
    if(!cardExistsIn(state.cards[player], card)) { return false; }
    
    const battle: Battle = state.battle;
    const playerCards: CardPattern[] = state.cards[player];
    let cardsAllowedToThrow: CardPattern[] = [];
    if (isTableEmpty(battle)) {
        //it will be first card on table, allow, no matter what it is
        cardsAllowedToThrow = playerCards;
    } else {
        //upcomming cards should be related to lead card
        cardsAllowedToThrow = getCardsByColor(playerCards, getCardSuit(getLeadCard(battle)));
        if(cardsAllowedToThrow.length === 0) {
            cardsAllowedToThrow = playerCards;
        } else {
            if (isTrumpAnnounced(battle)) {                
                cardsAllowedToThrow = [
                    ...cardsAllowedToThrow, 
                    ...getCardsByColor(playerCards, getTrumpSuit(battle))
                ];
            }
        }
    }
    
    return cardExistsIn(cardsAllowedToThrow, card);
}
 
export function isTrickFinished(state: Game): boolean {
    return state.battle.trickCards.length === 3;
}
 
export function isBattleFinished(state: Game): boolean {
    return _.chain(state.battle.wonCards)
        .reduce((total: number, playerCards: Card[]) => total + playerCards.length, 0)
        .isEqual(24)
        .value()
}